package com.qinglei.recoup.hmp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qinglei.recoup.common.domain.CommonRes;
import com.qinglei.recoup.common.exception.RedisConnectException;
import com.qinglei.recoup.common.service.RedisService;
import com.qinglei.recoup.common.service.impl.ProductCache;
import com.qinglei.recoup.common.tenant.TenantContextHolder;
import com.qinglei.recoup.common.utils.JsonUtils;
import com.qinglei.recoup.hmp.pojo.vo.*;
import com.qinglei.recoup.hmp.pojo.vo.healthReport.GqqSleepReportDayVO;
import com.qinglei.recoup.hmp.pojo.vo.healthReport.HealthReportDayVo;
import com.qinglei.recoup.hmp.pojo.vo.healthReport.TopVo;
import com.qinglei.recoup.hmp.service.HmpHealthReportService;
import com.qinglei.recoup.hmp.service.QingLeiHmpGqqService;
import com.qinglei.recoup.system.dao.BedHealthDailyStatisticsMapper;
import com.qinglei.recoup.system.dao.TBedHealthDailyStatisticsDataMapper;
import com.qinglei.recoup.system.domain.*;
import com.qinglei.recoup.system.pojo.*;
import com.qinglei.recoup.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author superman
 * @date 2022/6/6$ 21:22$
 */
@Slf4j
@Service
public class QingLeiHmpGqqServiceImpl implements QingLeiHmpGqqService {
    @Value("${recoup.tenant.default-vital-signs-alarm}")
    private String defaultVitalSignsAlarm;

    @Value("${recoup.tenant.default-real-time-monitoring}")
    private String defaultRealTimeMonitoring;

    @Autowired
    private BedService bedService;

    @Autowired
    private RoomService roomService;

    @Autowired
    private FloorService floorService;

    @Autowired
    private BuildingService buildingService;

    @Autowired
    private RadarService radarService;

    @Autowired
    private RadarBedService radarBedService;

    @Autowired
    private MonitorTimeService monitorTimeService;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private BedMonitorTimeService bedMonitorTimeService;

    @Resource
    private TBedHealthDailyStatisticsDataMapper tBedHealthDailyStatisticsDataMapper;

    @Autowired
    private BedHealthDailyStatisticsService bedHealthDailyStatisticsService;

    @Resource
    private BedHealthDailyStatisticsMapper bedHealthDailyStatisticsMapper;

    @Resource
    private HmpHealthReportService hmpHealthReportService;

    @Autowired
    private VitalSignsAlarmService vitalSignsAlarmService;

    @Autowired
    private RealTimeMonitoringService realTimeMonitoringService;

    @Autowired
    private RedisService redisService;

    // 院长床位表
    @Autowired
    private DeanBedService deanBedService;

    // 护工床位表
    @Autowired
    private NurseBedService nurseBedService;

    @Autowired
    private ProductCache productCache;

    @Autowired
    private BedInformationService bedInformationService;

    // 设备sn绑定事件
    @Override
    public CommonRes<Object> deviceSnBingBed(String sn, String type, String buildName, String floorName, String roomName, String bedName) {
        Integer tenantId = TenantContextHolder.DEFAULT_TENANT_ID;
        // 绑定雷达时, 给雷达预设 护理等级(半自理) 和 行动能力参数(可自行缓慢走动)
        // 1. 查看 sn 是否有 预设参数, 有就跳过, 没有就新增
        List<BedInformation> list = bedInformationService.lambdaQuery().eq(BedInformation::getSnCode, sn).list();
        if (CollUtil.isEmpty(list)) {
            BedInformation bedInformation = new BedInformation();
            bedInformation.setSnCode(sn);
            bedInformation.setName(DateUtil.today() + "预设参数");
            bedInformation.setSex(RandomUtil.randomInt() % 2);  // 随机性别
            bedInformation.setAgeGroup(3); // 年龄段 66-70岁
            bedInformation.setActionAbility(5); // 行动能力参数(可自行缓慢走动)
            bedInformation.setNursingLevel(2); // 护理等级(半自理)
            bedInformation.setBreath("6");// 呼吸(不存在呼吸问题)
            bedInformation.setHeart("5"); // 心脏(不存在心脏问题)
            bedInformation.setInsomnia(3); // 是否失明
            bedInformation.setSnore(3); // 是否打呼噜(很少)
            bedInformation.setNightFrequency(3); // 起夜频次(很少)
            bedInformation.setSleepDisorderedBreathing("[]");
            bedInformation.setCreateTime(LocalDateTime.now());
            bedInformation.setTenantId(tenantId);
            bedInformationService.saveOrUpdate(bedInformation);
        }

        // 调用方 雷达类型: 1-智能床垫  2-睡眠检测雷达  3-跌倒雷达(顶棚雷达)
        // 参数校验
        if (sn.length() != 8 && sn.length() != 12) {
            return CommonRes.failed("监测仪设备SN码(8或12个字符)");
        }
        if (CharSequenceUtil.isBlank(type)) {
            // 默认是 睡眠检测雷达
            type = "2";
        }
        // 绑定前先 检测 房间是否绑定 顶棚雷达, (要兼容, 能绑定多个顶棚雷达)
        // 找房间下的 顶棚雷达
        List<Radar> radarList = radarBedService.queryRadarListByRoomName(roomName);
        if (CollUtil.isNotEmpty(radarList)) {
            // 找房间下的所有床位
            List<Bed> bedList = radarBedService.queryBedListByRoomName(roomName);
            if (CollUtil.isNotEmpty(bedList)) {
                for (Radar radar : radarList) {
                    for (Bed bed : bedList) {
                        Integer count = radarBedService.lambdaQuery()
                                .eq(RadarBed::getRadarId, radar.getId())
                                .eq(RadarBed::getBedId, bed.getId()).count();
                        if (count <= 0) {
                            RadarBed entity = new RadarBed();
                            entity.setRadarId(radar.getId());
                            entity.setBedId(bed.getId());
                            // tenantId 相当于机构id
                            entity.setTenantId(tenantId);
                            radarBedService.save(entity);
                        }
                    }
                }
            }
        }

        // 2022-07-13 需求变更 跌倒雷达 绑定到房间  start
        if ("3".equals(type)) {
            // 如果是 睡眠检测雷达, 绑定至房间
            // 查询或创建雷达
            Radar radar = createNewRadar(sn, type);
            // 查询或创建 相应的房间
            Room room = createNewRoom(buildName, floorName, roomName);
            if (StrUtil.isNotBlank(bedName)) {
                createNewBad(bedName, buildName, floorName, roomName);
            }
            // 查询房间下的所有床位
            List<Bed> bedList = bedService.lambdaQuery().eq(Bed::getRoomId, room.getId())
                    .eq(Bed::getTenantId, tenantId).list();

            if (CollUtil.isNotEmpty(bedList)) {
                boolean saveFlag = true;
                // 将雷达绑定到房间内所有床位
                for (Bed bed : bedList) {
                    // 绑定 雷达 和 床位, 兼容 重复绑定, 先判断一下 是否已经绑定该顶棚雷达 和 房间内的床位
                    Integer count = radarBedService.lambdaQuery()
                            .eq(RadarBed::getRadarId, radar.getId())
                            .eq(RadarBed::getBedId, bed.getId()).count();
                    if (count <= 0) {
                        RadarBed entity = new RadarBed();
                        entity.setRadarId(radar.getId());
                        entity.setBedId(bed.getId());
                        // tenantId 相当于机构id
                        entity.setTenantId(tenantId);
                        boolean save = radarBedService.save(entity);
                        saveFlag = saveFlag && save;
                    }
                }
                if (saveFlag) {
                    return CommonRes.ok(true, "顶棚雷达设备绑定成功");
                } else {
                    return CommonRes.ok(false, "顶棚雷达设备绑定失败");
                }
            }
        }

        // 2022-07-13 需求变更 跌倒雷达 绑定到房间  end
        // 以下是 原绑定逻辑, 适用于 睡眠检测雷达
        // 1. 根据 sn码 查询 雷达-床位 绑定关系记录
        Radar radar = radarService.lambdaQuery().eq(Radar::getSnCode, sn).one();
        Bed bed;
        if (ObjectUtil.isNotEmpty(radar)) {
            // 已有雷达设备记录 ===> 查询雷达是否绑定设备
            List<RadarBed> radarBedList = radarBedService.lambdaQuery()
                    .eq(RadarBed::getIsDeleted, 0)
                    .eq(RadarBed::getRadarId, radar.getId()).list();
            if (CollUtil.isNotEmpty(radarBedList)) {
                // 雷达已绑定床位, 验证 床位名称  ==> 不验证, 直接返回, 未解绑提示
                return CommonRes.ok("该设备sn已存在绑定关系, 请勿重复绑定");
            } else {
                // 没有 绑定记录  ==>  先 创建一张床位, 再进行绑定关系
                bed = createNewBad(bedName, buildName, floorName, roomName);
            }
        } else {
            // 没有雷达设备记录, 先新增 雷达, 再 新增床位, 最后雷达绑定床位
            radar = createNewRadar(sn, type);
            bed = createNewBad(bedName, buildName, floorName, roomName);
        }
        if (ObjectUtil.isEmpty(radar)) {
            return CommonRes.failed(false, "初始化雷达信息异常");
        }
        // 绑定 雷达 和 床位
        RadarBed entity = new RadarBed();
        entity.setRadarId(radar.getId());
        entity.setBedId(bed.getId());
        // tenantId 相当于机构id
        entity.setTenantId(tenantId);
        boolean save = radarBedService.save(entity);
        if (save) {
            return CommonRes.ok(true, "设备绑定成功");
        } else {
            return CommonRes.ok(false, "设备绑定失败");
        }
    }

    @Override
    public CommonRes<Object> deviceSnDeBingBed(String sn) {
        // 参数校验
        if (sn.length() != 8 && sn.length() != 12) {
            return CommonRes.failed("监测仪设备SN码(8或12个字符)");
        }
        Radar radar = radarService.lambdaQuery().eq(Radar::getSnCode, sn).one();
        if (ObjectUtil.isEmpty(radar)) {
            return CommonRes.ok(true, "监测仪设备SN码不存在, 不需要解绑");
        }
        int delete = radarBedService.getBaseMapper().delete(Wrappers.<RadarBed>lambdaQuery()
                .eq(RadarBed::getRadarId, radar.getId()));
        if (delete > 0) {
            return CommonRes.ok(true, "设备sn解绑成功【" + delete + "】");
        } else {
            return CommonRes.failed(false, "设备sn已解绑");
        }
    }

    @Override
    public CommonRes<Object> deviceSnIsExist(String sn) {
        boolean existEquipment;
        try {
            existEquipment = productCache.isExistEquipment(sn);
        } catch (Exception e) {
            return CommonRes.failed("查询失败");
        }
        if (existEquipment) {
            return CommonRes.ok(existEquipment, "设备sn存在");
        } else {
            return CommonRes.ok(existEquipment, "设备sn不存在");
        }
    }

    @Override
    public CommonRes<List<HealthReportDayVo>> getsleepReportOneDay(String[] sn, String startDate, String endDate) {
        List<HealthReportDayVo> list = new ArrayList<>();
        for (String s : sn) {
            Radar radar = radarService.getOne(new QueryWrapper<Radar>().lambda().eq(Radar::getSnCode, s).eq(Radar::getType, 1));
            if (Objects.isNull(radar)) {
                return CommonRes.failed("该设备sn号{" + s + "}不存在");
            }
            if ("2".equals(radar.getType())) {
                return CommonRes.failed("不能用顶棚雷达sn查询健康报告! sn:【" + s + "】");
            }
            RadarBed radarBed = radarBedService.lambdaQuery()
                    .eq(RadarBed::getIsDeleted, 0)
                    .eq(RadarBed::getRadarId, radar.getId()).one();
            if (Objects.isNull(radarBed)) {
                return CommonRes.failed("该设备sn号{" + s + "}未绑定床位");
            }
            int bedId = radarBed.getBedId();
            long between = DateUtil.between(DateUtil.parse(startDate, "yyyy-MM-dd"),
                    DateUtil.parse(endDate, "yyyy-MM-dd"), DateUnit.DAY);
            for (int i = 0; i <= between; i++) {
                DateTime offset = DateUtil.offset(DateUtil.parse(startDate, "yyyy-MM-dd"),
                        DateField.DAY_OF_YEAR, i);
                String date = DateUtil.format(offset, "yyyy-MM-dd");
                CommonRes<HealthReportDayVo> healthReportDayVoCommonRes = hmpHealthReportService.getSleepReportOneDayByBedIdAndDate(bedId, date);
                HealthReportDayVo reportOneDay = healthReportDayVoCommonRes.getData();
                reportOneDay.setSn(s);
                list.add(reportOneDay);
            }
        }
        return CommonRes.ok(list);
    }

    // 获取指定日期的单日报告
    private GqqSleepReportDayVO getReportOneDay(LocalDate date, int bedId, String sn) {
        SleepReportMoreVO reportMore4Hmp = bedHealthDailyStatisticsService.getReportMore4Hmp(bedId, date, date);
        GqqSleepReportDayVO sleepReportDayVO = new GqqSleepReportDayVO();
        BeanUtil.copyProperties(reportMore4Hmp, sleepReportDayVO);
        // 1. 修改 statisticsDate
        try {
            sleepReportDayVO.setStatisticsDate(sleepReportDayVO.getStatisticsDate().split("-")[0].trim());
        } catch (Exception e) {
            e.printStackTrace();
        }
        sleepReportDayVO.setSn(sn);
        return sleepReportDayVO;
    }

    @Override
    public CommonRes<List<HmpSleepReportMoreVO>> getsleepReportMoreDay(String[] sn, String startDateStr, String endDateStr) {
        LocalDate startDate = LocalDate.parse(startDateStr);
        LocalDate endDate = LocalDate.parse(endDateStr);
        List<HmpSleepReportMoreVO> list = new ArrayList<>();
        for (String s : sn) {
            HmpSleepReportMoreVO hmpSleepReportMoreVO = new HmpSleepReportMoreVO();
            Radar radar = radarService.getOne(new QueryWrapper<Radar>().lambda().eq(Radar::getSnCode, s).eq(Radar::getType, 1));
            if (Objects.isNull(radar)) {
                return CommonRes.failed("该设备sn号不存在");
            }
            if ("2".equals(radar.getType())) {
                return CommonRes.failed("不能用顶棚雷达sn查询健康报告! sn:【" + s + "】");
            }
            RadarBed radarBed = radarBedService.lambdaQuery().eq(RadarBed::getRadarId, radar.getId()).one();
            if (Objects.isNull(radarBed)) {
                return CommonRes.failed("该设备sn号未绑定床位");
            }
            int bedId = radarBed.getBedId();
            SleepReportMoreVO reportMore4Hmp = bedHealthDailyStatisticsService.getReportMore4Hmp(bedId, startDate, endDate);
            if (reportMore4Hmp == null) {
                return CommonRes.failed("缺少健康报告数据");
            }
            hmpSleepReportMoreVO = new HmpSleepReportMoreVO();
            hmpSleepReportMoreVO.setBedId(reportMore4Hmp.getBedId());
            hmpSleepReportMoreVO.setBedName(reportMore4Hmp.getBedName());
            hmpSleepReportMoreVO.setStatisticsDate(reportMore4Hmp.getStatisticsDate());
            int dayNum = Period.between(startDate, endDate).getDays() + 1;
            hmpSleepReportMoreVO.setDayNum(dayNum);
            hmpSleepReportMoreVO.setEndDate(endDate.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
            // 查询有统计报告的第一天
            BedHealthDailyStatistics firstDate = bedHealthDailyStatisticsService.getOne(Wrappers.<BedHealthDailyStatistics>lambdaQuery()
                    .eq(BedHealthDailyStatistics::getBedId, reportMore4Hmp.getBedId())
                    .last("order by statistics_date asc limit 1"));
            hmpSleepReportMoreVO.setFirstDate(firstDate.getStatisticsDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            Map<String, Object> resultMapSrc = reportMore4Hmp.getResultMap();
            ResultMapVO resultMap = new ResultMapVO();
            if (resultMapSrc.get("ahiAVG") != null) {
                resultMap.setAhiAVG((Double) resultMapSrc.get("ahiAVG"));
            }
            if (resultMapSrc.get("ahiX") != null) {
                resultMap.setAhiX((List<String>) resultMapSrc.get("ahiX"));
            }
            if (resultMapSrc.get("ahiy") != null) {
                resultMap.setAhiy((List<Double>) resultMapSrc.get("ahiy"));
            }

            if (resultMapSrc.get("scoreAVG") != null) {
                resultMap.setScoreAVG(((Double) resultMapSrc.get("scoreAVG")).intValue());
            }
            if (resultMapSrc.get("scoreX") != null) {
                resultMap.setScoreX((List<String>) resultMapSrc.get("scoreX"));
            }
            if (resultMapSrc.get("scoreY") != null) {
                resultMap.setScoreY((List<Double>) resultMapSrc.get("scoreY"));
            }

            if (resultMapSrc.get("moraleAVG") != null) {
                resultMap.setMoraleAVG(((Double) resultMapSrc.get("moraleAVG")).intValue());
            }
            if (resultMapSrc.get("moraleX") != null) {
                resultMap.setMoraleX((List<String>) resultMapSrc.get("moraleX"));
            }
            if (resultMapSrc.get("moraleY") != null) {
                resultMap.setMoraleY((List<Integer>) resultMapSrc.get("moraleY"));
            }

            if (resultMapSrc.get("fallAVG") != null) {
                resultMap.setFallAVG(((Double) resultMapSrc.get("fallAVG")).intValue());
            }
            if (resultMapSrc.get("fallX") != null) {
                resultMap.setFallX((List<String>) resultMapSrc.get("fallX"));
            }
            if (resultMapSrc.get("fallY") != null) {
                resultMap.setFallY((List<Integer>) resultMapSrc.get("fallY"));
            }

            if (resultMapSrc.get("vitalityAVG") != null) {
                resultMap.setVitalityAVG(((Double) resultMapSrc.get("vitalityAVG")).intValue());
            }
            if (resultMapSrc.get("vitalityX") != null) {
                resultMap.setVitalityX((List<String>) resultMapSrc.get("vitalityX"));
            }
            if (resultMapSrc.get("vitalityY") != null) {
                resultMap.setVitalityY((List<Integer>) resultMapSrc.get("vitalityY"));
            }
            hmpSleepReportMoreVO.setResultMap(resultMap);

            // sleepDurationChart
            SleepDurationChartVO sleepDurationChartVO = new SleepDurationChartVO();
            sleepDurationChartVO.setSleepSum(reportMore4Hmp.getSleepSum());
            sleepDurationChartVO.setSleepAvg(reportMore4Hmp.getSleepAvg());
            sleepDurationChartVO.setSleepMoreVOS(reportMore4Hmp.getSleepMoreVOS());
            hmpSleepReportMoreVO.setSleepDurationChart(sleepDurationChartVO);

            // 离床次数图表数据
            HmpChartDataVO<Integer> outBedNum = new HmpChartDataVO<>();
            List<OutBedNumMoreVO> outBedNumSrc = reportMore4Hmp.getOutBedNum();
            if (outBedNumSrc != null) {
                List<StatisticsDataItemVO<Integer>> data = new ArrayList<>();
                int sum = 0;
                int cnt = 0;
                for (OutBedNumMoreVO outBedNumMoreVO : outBedNumSrc) {
                    StatisticsDataItemVO<Integer> item = new StatisticsDataItemVO<>();
                    item.setStatisticsDate(outBedNumMoreVO.getStatisticsDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                    item.setData(outBedNumMoreVO.getOutBedNum());
                    data.add(item);
                    if (outBedNumMoreVO.getOutBedNum() != null) {
                        sum += outBedNumMoreVO.getOutBedNum();
                        cnt++;
                    }
                }
                outBedNum.setData(data);
                if (cnt > 0) {
                    outBedNum.setAvg(Math.round(((float) sum) / cnt));
                } else {
                    outBedNum.setAvg(0);
                }
                hmpSleepReportMoreVO.setOutBedNum(outBedNum);
            }

            // 离床时长图表数据
            HmpChartDataVO<Integer> outBedDuration = new HmpChartDataVO<>();
            List<OutBedDurationMoreVO> outBedDurationSrc = reportMore4Hmp.getOutBedDuration();
            if (outBedDurationSrc != null) {
                List<StatisticsDataItemVO<Integer>> data = new ArrayList<>();
                int sum = 0;
                int cnt = 0;
                for (OutBedDurationMoreVO outBedDurationMoreVO : outBedDurationSrc) {
                    StatisticsDataItemVO<Integer> item = new StatisticsDataItemVO<>();
                    item.setStatisticsDate(outBedDurationMoreVO.getStatisticsDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                    item.setData(outBedDurationMoreVO.getOutBedMinute());
                    item.setDuration(outBedDurationMoreVO.getOutBedDuration());
                    data.add(item);
                    if (outBedDurationMoreVO.getOutBedMinute() != null) {
                        sum += outBedDurationMoreVO.getOutBedMinute();
                        cnt++;
                    }
                }
                outBedDuration.setData(data);
                if (cnt > 0) {
                    outBedDuration.setAvg(Math.round(((float) sum) / cnt));
                } else {
                    outBedDuration.setAvg(0);
                }
                hmpSleepReportMoreVO.setOutBedDuration(outBedDuration);
            }

            // 翻身图表数据
            HmpChartDataVO<Integer> turnOver = new HmpChartDataVO<>();
            List<TurnOverMoreNum> turnOverMoreNums = reportMore4Hmp.getTurnOverMoreNums();
            if (turnOverMoreNums != null) {
                List<StatisticsDataItemVO<Integer>> data = new ArrayList<>();
                for (TurnOverMoreNum turnOverMoreNum : turnOverMoreNums) {
                    StatisticsDataItemVO<Integer> item = new StatisticsDataItemVO<>();
                    item.setStatisticsDate(turnOverMoreNum.getStatisticsDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                    item.setData(turnOverMoreNum.getTurnOverNum());
                    data.add(item);
                }
                turnOver.setData(data);
                turnOver.setAvg((int) Math.round(reportMore4Hmp.getTurnOverMoreAvg()));
                hmpSleepReportMoreVO.setTurnOver(turnOver);
            }

            // breathRuleData
            HealthDetailParamV1 healthDetailParamV1 = new HealthDetailParamV1();
            healthDetailParamV1.setBedId(reportMore4Hmp.getBedId());
            healthDetailParamV1.setStartTime(startDate);
            healthDetailParamV1.setEndTime(endDate);
            Map<String, Object> healthReportV3 = (Map<String, Object>) bedHealthDailyStatisticsService.getHealthReportV3(healthDetailParamV1);
            if (healthReportV3 != null) {
                BreathRuleDataVO breathRuleData = new BreathRuleDataVO();
                breathRuleData.setMin((Integer) healthReportV3.get("breathDataMin"));
                breathRuleData.setMax((Integer) healthReportV3.get("breathDataMax"));
                breathRuleData.setAvg((int) ((long) healthReportV3.get("breathDataAvg")));
                breathRuleData.setBreathData(healthReportV3.get("breathData"));
                hmpSleepReportMoreVO.setBreathRuleData(breathRuleData);
            }

            // heartRuleData
            Map<String, Object> healthReportV2 = (Map<String, Object>) bedHealthDailyStatisticsService.getHealthReportV2(healthDetailParamV1);
            if (healthReportV2 != null) {
                HeartRuleDataVO heartRuleData = new HeartRuleDataVO();
                heartRuleData.setMin((Integer) healthReportV2.get("heartDataMin"));
                heartRuleData.setMax((Integer) healthReportV2.get("heartDataMax"));
                heartRuleData.setAvg((int) ((long) healthReportV2.get("heartDataAvg")));
                heartRuleData.setHeartData(healthReportV2.get("heartData"));
                hmpSleepReportMoreVO.setHeartRuleData(heartRuleData);

                // sleepRuleData
                hmpSleepReportMoreVO.setSleepRuleData(healthReportV2.get("sleepRule"));
            }

            // sleepSug
            if (dayNum > 7) {
                Object reportInterpretation = bedHealthDailyStatisticsService.getReportInterpretation(healthDetailParamV1);
                hmpSleepReportMoreVO.setSleepSug(reportInterpretation);
            }
            hmpSleepReportMoreVO.setSn(s);
            list.add(hmpSleepReportMoreVO);
        }

        return CommonRes.ok(list);
    }

    // 情绪指数排行榜
    @Override
    public CommonRes<List<TopVo>> queryMoraleTopList(int offset, String[] snList) {
        List<TopVo> list = new ArrayList<>();
        for (String sn : snList) {
            TopVo topVo = new TopVo();
            topVo.setSn(sn);
            Bed bed = bedService.getBedBySn(sn);
            if (null == bed) {
                // sn未绑定, 跳过
                continue;
            }
            // 查询前一天的报告
            TBedHealthDailyStatisticsData one = tBedHealthDailyStatisticsDataMapper.selectOne(
                    new QueryWrapper<TBedHealthDailyStatisticsData>().lambda()
                            .eq(TBedHealthDailyStatisticsData::getStatisticsDate, LocalDate.now().minusDays(offset))
                            .eq(TBedHealthDailyStatisticsData::getBedId, bed.getId()));
            if (ObjectUtil.isEmpty(one)) {
                // 未查询到报告, 跳过
                continue;
            }
            topVo.setValue(null == one.getMoraleIndex() ? "0.0" : one.getMoraleIndex() + "");
            topVo.setBedNo(one.getBedName());
            topVo.setTrend("up");
            // 判断趋势, 找前一天的数据
            TBedHealthDailyStatisticsData two = tBedHealthDailyStatisticsDataMapper.selectOne(
                    new QueryWrapper<TBedHealthDailyStatisticsData>().lambda()
                            .eq(TBedHealthDailyStatisticsData::getStatisticsDate, LocalDate.now().minusDays(offset + 1))
                            .eq(TBedHealthDailyStatisticsData::getBedId, bed.getId()));
            if (ObjectUtil.isNotEmpty(two)) {
                if (two.getMoraleIndex() != null && one.getMoraleIndex() != null && two.getMoraleIndex() > one.getMoraleIndex()) {
                    topVo.setTrend("down");
                } else {
                    topVo.setTrend("up");
                }
            }
            list.add(topVo);
        }
        // 排序, 设置排名
        list.sort((o1, o2) -> Double.compare(Double.parseDouble(o2.getValue()), Double.parseDouble(o1.getValue())));

        for (int i = 0; i < list.size(); i++) {
            TopVo topVo = list.get(i);
            topVo.setRank(i + 1 + "");
        }
        return CommonRes.ok(list);
    }

    // 跌倒风险指数排行榜
    @Override
    public CommonRes<List<TopVo>> queryFailTopList(int offset, String[] snList) {
        List<TopVo> list = new ArrayList<>();
        for (String sn : snList) {
            TopVo topVo = new TopVo();
            topVo.setSn(sn);
            Bed bed = bedService.getBedBySn(sn);
            if (null == bed) {
                // sn未绑定, 跳过
                continue;
            }
            // 查询前一天的报告
            TBedHealthDailyStatisticsData one = tBedHealthDailyStatisticsDataMapper.selectOne(
                    new QueryWrapper<TBedHealthDailyStatisticsData>().lambda()
                            .eq(TBedHealthDailyStatisticsData::getStatisticsDate, LocalDate.now().minusDays(offset))
                            .eq(TBedHealthDailyStatisticsData::getBedId, bed.getId()));
            if (ObjectUtil.isEmpty(one)) {
                // 未查询到报告, 跳过
                continue;
            }
            topVo.setValue(null == one.getFallIndex() ? "0.0" : one.getFallIndex() + "");
            topVo.setBedNo(one.getBedName());
            topVo.setTrend("up");
            // 判断趋势, 找前一天的数据
            TBedHealthDailyStatisticsData two = tBedHealthDailyStatisticsDataMapper.selectOne(
                    new QueryWrapper<TBedHealthDailyStatisticsData>().lambda()
                            .eq(TBedHealthDailyStatisticsData::getStatisticsDate, LocalDate.now().minusDays(offset + 1))
                            .eq(TBedHealthDailyStatisticsData::getBedId, bed.getId()));
            if (ObjectUtil.isNotEmpty(two)) {
                if (two.getFallIndex() != null && one.getFallIndex() != null && two.getFallIndex() > one.getFallIndex()) {
                    topVo.setTrend("down");
                } else {
                    topVo.setTrend("up");
                }
            }
            list.add(topVo);
        }
        // 排序, 设置排名
        list.sort((o1, o2) -> Double.compare(Double.parseDouble(o2.getValue()), Double.parseDouble(o1.getValue())));

        for (int i = 0; i < list.size(); i++) {
            TopVo topVo = list.get(i);
            topVo.setRank(i + 1 + "");
        }
        return CommonRes.ok(list);
    }

    // 活力指数排行榜
    @Override
    public CommonRes<List<TopVo>> queryVitalityTopList(int offset, String[] snList) {
        List<TopVo> list = new ArrayList<>();
        for (String sn : snList) {
            TopVo topVo = new TopVo();
            topVo.setSn(sn);
            Bed bed = bedService.getBedBySn(sn);
            if (null == bed) {
                // sn未绑定, 跳过
                continue;
            }
            // 查询前一天的报告
            TBedHealthDailyStatisticsData one = tBedHealthDailyStatisticsDataMapper.selectOne(
                    new QueryWrapper<TBedHealthDailyStatisticsData>().lambda()
                            .eq(TBedHealthDailyStatisticsData::getStatisticsDate, LocalDate.now().minusDays(offset))
                            .eq(TBedHealthDailyStatisticsData::getBedId, bed.getId()));
            if (ObjectUtil.isEmpty(one)) {
                // 未查询到报告, 跳过
                continue;
            }
            topVo.setValue(null == one.getVitalityIndex() ? "0.0" : one.getVitalityIndex() + "");
            topVo.setBedNo(one.getBedName());
            topVo.setTrend("up");
            // 判断趋势, 找前一天的数据
            TBedHealthDailyStatisticsData two = tBedHealthDailyStatisticsDataMapper.selectOne(
                    new QueryWrapper<TBedHealthDailyStatisticsData>().lambda()
                            .eq(TBedHealthDailyStatisticsData::getStatisticsDate, LocalDate.now().minusDays(offset + 1))
                            .eq(TBedHealthDailyStatisticsData::getBedId, bed.getId()));
            if (ObjectUtil.isNotEmpty(two)) {
                if (two.getVitalityIndex() != null && one.getVitalityIndex() != null && two.getVitalityIndex() > one.getVitalityIndex()) {
                    topVo.setTrend("down");
                } else {
                    topVo.setTrend("up");
                }
            }
            list.add(topVo);
        }
        // 排序, 设置排名
        list.sort((o1, o2) -> Double.compare(Double.parseDouble(o2.getValue()), Double.parseDouble(o1.getValue())));

        for (int i = 0; i < list.size(); i++) {
            TopVo topVo = list.get(i);
            topVo.setRank(i + 1 + "");
        }
        return CommonRes.ok(list);
    }

    // 查询用户的健康数据列表
    @Override
    public List<HealthVO> searchHealthList(String[] snList, String startDate, String endDate) {
        // 用户 对应的 一组 设备sn, 作为参数 传入
        List<Radar> radarList = radarService.lambdaQuery().in(Radar::getSnCode, snList).list();
        List<Integer> radarIdList = radarList.stream().map(Radar::getId).collect(Collectors.toList());
        List<RadarBed> radarBedList = radarBedService.lambdaQuery().in(RadarBed::getRadarId, radarIdList).list();
        List<Integer> bedIdsByUser = radarBedList.stream().map(RadarBed::getBedId).collect(Collectors.toList());
        if (org.apache.commons.collections.CollectionUtils.isEmpty(bedIdsByUser) || bedIdsByUser.get(0) == 0) {
            return new ArrayList<>();
        }
        // 生成查询条件
        HealthSearchQO healthSearchQO = new HealthSearchQO();
        Integer tenantId = TenantContextHolder.getTenantId();
        healthSearchQO.setTenantId(tenantId);
        // 设置床位条件
        if (bedIdsByUser.get(0) != -1) {
            healthSearchQO.setBedIds(bedIdsByUser);
        }
        // 设置起止时间条件
        healthSearchQO.setStartDate(LocalDate.parse(startDate));
        healthSearchQO.setEndDate(LocalDate.parse(endDate));
        // 设置分页参数
        Page<HealthVO> page = new Page<>(1, 1000);
        OrderItem orderItem = new OrderItem();
        OrderItem orderItem1 = new OrderItem();
        orderItem1.setColumn("deepSleepDuration  IS NULL, deepSleepDuration");
        orderItem.setColumn("score is null,score");
        page.getOrders().add(orderItem);
        page.getOrders().add(orderItem1);
        List<Integer> bedIdsByUserTemp = new ArrayList<>();
        if (bedIdsByUser != null && bedIdsByUser.get(0) == -1) {
            QueryWrapper queryWrapperB = new QueryWrapper();
            queryWrapperB.eq("tenant_id", TenantContextHolder.DEFAULT_TENANT_ID);
            queryWrapperB.eq("is_deleted", 0);
            List<Bed> bedsList = bedService.getBaseMapper().selectList(queryWrapperB);
            bedsList.forEach(bed -> {
                if (bedService.isBed(bed.getId())) {
                    bedIdsByUserTemp.add(bed.getId());
                }
            });
        } else {
            bedIdsByUser.forEach(t -> {
                if (bedService.isBed(t)) {
                    bedIdsByUserTemp.add(t);
                }
            });
        }
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.in("bed_id", bedIdsByUserTemp);
        queryWrapper.between("statistics_date", startDate, endDate);
        Integer count = bedHealthDailyStatisticsService.getBaseMapper().selectCount(queryWrapper);
        healthSearchQO.setBedIds(bedIdsByUserTemp);
        IPage<HealthVO> healthVOIPage = bedHealthDailyStatisticsMapper.selectHealthPage(page, healthSearchQO);
        if (count > 0) {
            List<HealthVO> records = healthVOIPage.getRecords();
            records.stream().forEach(item -> {
                RadarBed one = radarBedService.getOne(new QueryWrapper<RadarBed>().lambda().eq(RadarBed::getBedId, item.getBedId()).eq(RadarBed::getIsDeleted, 0).last("LIMIT 1"));
                if (!Objects.isNull(one)) {
                    Radar byId = radarService.getById(one.getRadarId());
                    if (!Objects.isNull(byId) && StringUtils.isNotEmpty(byId.getSnCode())) {
                        item.setSn(byId.getSnCode());
                    }
                }
            });
            return records;
        } else {
            return new ArrayList<>();
        }
    }

    // 设备生命体征报警阈值-批量查询
    @Override
    public CommonRes<List<VitalSignsAlarm>> selectVitalSignsAlarm(String[] snList) {
        List<VitalSignsAlarm> list = new ArrayList<>();
        for (String sn : snList) {
            Bed bed = bedService.getBedBySn(sn);
            List<VitalSignsAlarm> vitalSignsAlarmList = vitalSignsAlarmService.lambdaQuery().eq(VitalSignsAlarm::getBedId, bed.getId()).list();
            if (CollUtil.isNotEmpty(vitalSignsAlarmList)) {
                vitalSignsAlarmList = vitalSignsAlarmList.stream().map(o -> o.setSn(sn)).collect(Collectors.toList());
                list.addAll(vitalSignsAlarmList);
            }
        }
        return CommonRes.ok(list);
    }

    // 设备生命体征报警阈值-批量修改
    @Override
    public CommonRes<Object> updateVitalSignsAlarm(List<VitalSignsAlarm> vitalSignsAlarmList) {
        //修改
        vitalSignsAlarmService.updateBatchById(vitalSignsAlarmList);
        vitalSignsAlarmList.forEach(t -> {
            if (t.getSignType() == 1 && t.getEnable() == 1) {
                List<Building> buildings = buildingService.lambdaQuery()
                        .eq(Building::getTenantId, TenantContextHolder.DEFAULT_TENANT_ID).list();
                buildings.forEach(s -> {
                    UpdateOutBedTimeoutParam param1 = new UpdateOutBedTimeoutParam();
                    param1.setObjId("b" + s.getId());
                    param1.setType(4);
                    param1.setOutBedTimeout(LocalTime.of(0, 0, Integer.parseInt(t.getContinued())).toString());
                    monitorTimeService.updateOutBedTimeout(param1);
                });
            }
        });
        List<VitalSignsAlarm> VitalSignsAlarmList2 = vitalSignsAlarmService.lambdaQuery()
                .eq(VitalSignsAlarm::getTenantId, TenantContextHolder.DEFAULT_TENANT_ID).list();
        VitalSignsAlarmList2.forEach(f -> {
            f.setCreateTime(null);
            f.setModifyTime(null);
            String s = JsonUtils.objectToJson(f);
            try {
                redisService.set("VitalSignsAlarm-" + f.getTenantId() + "-" + f.getSignType(), s);
            } catch (RedisConnectException e) {
                e.printStackTrace();
            }
        });
        return CommonRes.ok("修改成功");
    }

    // 生命体征报警阈值-查询默认值
    @Override
    public CommonRes<List<VitalSignsAlarm>> defaultVitalSignsAlarm() {
        // 生命体征报警类别(1.离床过久2.跌倒3.呼吸过速4.呼吸暂停过久5.心跳过缓6.心跳过速)
        return CommonRes.ok(JsonUtils.jsonToList(defaultVitalSignsAlarm, VitalSignsAlarm.class));
    }

    // 呼吸/心跳 阈值设置-批量查询
    @Override
    public CommonRes<List<RealTimeMonitoring>> selectRealTimeMonitoring(String[] snList) {
        List<RealTimeMonitoring> list = new ArrayList<>();
        for (String sn : snList) {
            Bed bed = bedService.getBedBySn(sn);
            List<RealTimeMonitoring> realTimeMonitoringList = realTimeMonitoringService.lambdaQuery()
                    .eq(RealTimeMonitoring::getBedId, bed.getId()).list();
            if (ObjectUtil.isNotEmpty(realTimeMonitoringList)) {
                realTimeMonitoringList = realTimeMonitoringList.stream().map(o -> o.setSn(sn)).collect(Collectors.toList());
                list.addAll(realTimeMonitoringList);
            }
        }
        return CommonRes.ok(list);
    }

    // 呼吸/心跳 阈值设置-批量修改
    @Override
    public CommonRes<Object> updateRealTimeMonitoring(List<RealTimeMonitoring> realTimeMonitoringList) {
        realTimeMonitoringService.updateBatchById(realTimeMonitoringList);
        List<RealTimeMonitoring> RealTimeMonitoringList2 = realTimeMonitoringService.lambdaQuery()
                .eq(RealTimeMonitoring::getTenantId, TenantContextHolder.DEFAULT_TENANT_ID).list();
        RealTimeMonitoringList2.forEach(f -> {
            f.setCreateTime(null);
            f.setModifyTime(null);
        });
        String s1 = JsonUtils.objectToJson(RealTimeMonitoringList2);
        try {
            redisService.set("RealTimeMonitoring-" + RealTimeMonitoringList2.get(0).getTenantId(), s1);
        } catch (RedisConnectException e) {
            e.printStackTrace();
        }
        return CommonRes.ok("修改成功");
    }

    // 呼吸/心跳 阈值设置-查询默认值
    @Override
    public CommonRes<List<RealTimeMonitoring>> defaultRealTimeMonitoring() {
        return CommonRes.ok(JsonUtils.jsonToList(defaultRealTimeMonitoring, RealTimeMonitoring.class));
    }

    // 查指定设备的配置树
    @Override
    public List<MonitorInfoTreeVO> getMonitorInfoTree(String sn) {
        Bed bed = bedService.getBedBySn(sn);
        Integer buildingId = bed.getBuildingId();
        Integer floorId = bed.getFloorId();
        Integer roomId = bed.getRoomId();
        Integer bedId = bed.getId();
        List<MonitorInfoTreeVO> buildingList = new ArrayList<>();
        Building building = buildingService.lambdaQuery().eq(Building::getId, buildingId).one();
        MonitorInfoTreeVO monitorInfoTreeVO = new MonitorInfoTreeVO();
        monitorInfoTreeVO.setId(BedService.TREE_BUILDING_PREFIX + buildingId);
        monitorInfoTreeVO.setKey(monitorInfoTreeVO.getId());
        monitorInfoTreeVO.setName(building.getName());
        monitorInfoTreeVO.setType(BedService.TYPE_BUILDING);
        monitorInfoTreeVO.setMonitorTimeUnified(building.getMonitorTimeUnified());
        monitorInfoTreeVO.setOutBedTimeoutUnified(building.getOutBedTimeoutUnified());
        monitorInfoTreeVO.setOutBedTime(building.getOutBedTimeout());
        List<MonitorTime> monitorTimes = monitorTimeService.lambdaQuery().eq(MonitorTime::getType, BedService.TYPE_BUILDING).eq(MonitorTime::getObjId, building.getId()).list();
        List<MonitorTimeVO> monitorTime = getMonitorTime(monitorTimes);
        monitorInfoTreeVO.setMonitorTimes(monitorTime);
        monitorInfoTreeVO.setChildren(getFloor(floorId, roomId, bedId));
        buildingList.add(monitorInfoTreeVO);
        return buildingList;
    }

    /**
     * 根据设备sn号创建一个设备, 如果已有设备, 则返回该设备
     */
    private Radar createNewRadar(String sn, String type) {
        // 获取默认 租户id
        Integer tenantId = TenantContextHolder.DEFAULT_TENANT_ID;
        Radar one = radarService.lambdaQuery().eq(Radar::getSnCode, sn).one();
        if (ObjectUtil.isNotEmpty(one)) {
            return one;
        }
        Radar radar = new Radar();
        radar.setSnCode(sn);
        radar.setType(Integer.parseInt(type) - 1);
        radar.setTenantId(tenantId);
        boolean save = radarService.save(radar);
        if (save) {
            return radar;
        } else {
            return null;
        }
    }

    /**
     * 根据床位名称创建一张床, 如果已存在就返回该床
     */
    private Bed createNewBad(String bedName, String buildingIndex, String floorIndex, String roomIndex) {
        Room room = createNewRoom(buildingIndex, floorIndex, roomIndex);
        int buildingId = room.getBuildingId();
        int floorId = room.getFloorId();
        int roomId = room.getId();
        Integer tenantId = TenantContextHolder.DEFAULT_TENANT_ID;
        //查询房间中是否有该名称的床位
        Bed bed = bedService.lambdaQuery().eq(Bed::getRoomId, roomId).eq(Bed::getTenantId, tenantId)
                .eq(Bed::getName, bedName).one();
        if (ObjectUtil.isNotEmpty(bed)) {
            return bed;
        }
        bed = new Bed();
        bed.setBuildingId(buildingId);
        bed.setFloorId(floorId);
        bed.setRoomId(roomId);
        bed.setName(bedName);
        bed.setTenantId(tenantId);
        // 离床时间阈值
        bed.setOutBedTimeout(room.getOutBedTimeout());
        int count = bedService.getBaseMapper().insert(bed);
        if (count > 0) {
            // 设置 默认 设备生命体征报警阈值
            List<VitalSignsAlarm> vitalSignsAlarmList = new ArrayList<>();
            List<VitalSignsAlarm> vitalSignsAlarms = JsonUtils.jsonToList(defaultVitalSignsAlarm, VitalSignsAlarm.class);
            for (VitalSignsAlarm vitalSignsAlarm : vitalSignsAlarms) {
                vitalSignsAlarm.setTenantId(tenantId);
                vitalSignsAlarm.setBuildingId(buildingId);
                vitalSignsAlarm.setFloorId(floorId);
                vitalSignsAlarm.setRoomId(roomId);
                vitalSignsAlarm.setBedId(bed.getId());
                vitalSignsAlarm.setEnable(1);
                vitalSignsAlarmList.add(vitalSignsAlarm);
            }
            vitalSignsAlarmService.saveBatch(vitalSignsAlarmList);
            // 设置 呼吸/心跳 阈值设置
            ArrayList<RealTimeMonitoring> realTimeMonitoringList = new ArrayList<>();
            List<RealTimeMonitoring> realTimeMonitorings = JsonUtils.jsonToList(defaultRealTimeMonitoring, RealTimeMonitoring.class);
            for (RealTimeMonitoring realTimeMonitoring : realTimeMonitorings) {
                realTimeMonitoring.setTenantId(tenantId);
                realTimeMonitoring.setBuildingId(buildingId);
                realTimeMonitoring.setFloorId(floorId);
                realTimeMonitoring.setRoomId(roomId);
                realTimeMonitoring.setBedId(bed.getId());
                realTimeMonitoring.setEnable(1);
                realTimeMonitoringList.add(realTimeMonitoring);
            }
            realTimeMonitoringService.saveBatch(realTimeMonitoringList);
            //获取上层检测时间设置
            List<TimePeriodParam> monitorTimeList = monitorTimeService.getMonitorTimeByObjIdAndType(roomId, BedService.TYPE_ROOM);
            if (CollectionUtils.isEmpty(monitorTimeList)) {
                // 添加默认检测时间
                monitorTimeList = systemConfigService.getDefaultMonitorTime();
            }
            // 更新 楼-层-房间 床位数
            buildingService.addBedCnt(buildingId);
            floorService.addBedCnt(floorId);
            roomService.addBedCnt(roomId);
            //同步床位所有监测时间段
            try {
                bedMonitorTimeService.syncMonitorTimes(monitorTimeList, bed.getId());
            } catch (Exception e) {
                log.error("新增床位: 同步床位所有监测时间段 异常");
            }
            // 加入 院长床位表, 护士床位表
            DeanBed deanBed = new DeanBed();
            deanBed.setUserId(TenantContextHolder.DEFAULT_DEAN_ID);
            deanBed.setType(BedService.TYPE_BED);
            deanBed.setObjId(bed.getId());
            deanBedService.save(deanBed);
            NurseBed nurseBed = new NurseBed();
            nurseBed.setUserId(TenantContextHolder.DEFAULT_NURSE_ID);
            nurseBed.setBedId(bed.getId());
            nurseBedService.save(nurseBed);
        }
        return bed;
    }

    /**
     * 新建一个房间
     *
     * @param buildingIndex 楼唯一标识
     * @param floorIndex    层唯一标识
     * @param roomIndex     房间唯一标识
     * @return 房间
     */
    private Room createNewRoom(String buildingIndex, String floorIndex, String roomIndex) {
        Integer tenantId = TenantContextHolder.DEFAULT_TENANT_ID;
        Floor floor = createNewFloor(buildingIndex, floorIndex);
        Room room = roomService.lambdaQuery()
                .eq(Room::getBuildingId, floor.getBuildingId())
                .eq(Room::getFloorId, floor.getId())
                .eq(Room::getName, roomIndex).one();
        if (ObjectUtil.isNotEmpty(room)) {
            return room;
        }
        // 没有 该房间
        room = new Room();
        room.setName(roomIndex);
        room.setTenantId(tenantId);
        room.setBuildingId(floor.getBuildingId());
        room.setFloorId(floor.getId());
        room.setIsDeleted(0);
        room.setBedCnt(0);
        //离床时间阈值
        room.setOutBedTimeout(floor.getOutBedTimeout());
        room.setOutBedTimeoutUnified(floor.getOutBedTimeoutUnified());
        //监测时间
        room.setMonitorTimeUnified(floor.getMonitorTimeUnified());
        int count = roomService.getBaseMapper().insert(room);
        List<TimePeriodParam> monitorTimeByObjIdandtype = monitorTimeService.getMonitorTimeByObjIdAndType(floor.getId(), SystemConfigService.TYPE_OUT_BED_TIMEOUT);
        if (CollUtil.isNotEmpty(monitorTimeByObjIdandtype)) {
            for (TimePeriodParam mtq : monitorTimeByObjIdandtype) {
                MonitorTime monitorTime = new MonitorTime();
                BeanUtils.copyProperties(mtq, monitorTime);
                monitorTime.setObjId(room.getId());
                monitorTime.setType(SystemConfigService.TYPE_TOUR_TIME);
                monitorTimeService.getBaseMapper().insert(monitorTime);
            }
        } else {
            List<TimePeriodParam> monitorTimeList = systemConfigService.getDefaultMonitorTime();
            for (TimePeriodParam sc : monitorTimeList) {
                MonitorTime monitorTime = new MonitorTime();
                monitorTime.setStartTime(sc.getStartTime());
                monitorTime.setEndTime(sc.getEndTime());
                monitorTime.setObjId(room.getId());
                monitorTime.setType(SystemConfigService.TYPE_TOUR_TIME);
                monitorTimeService.getBaseMapper().insert(monitorTime);
            }
        }
        if (count > 0) {
            return room;
        }
        throw new RuntimeException("新增房间失败");
    }

    /**
     * 新建一个楼层
     *
     * @param buildingIndex 楼唯一标识
     * @param floorIndex    层唯一标识
     * @return
     */
    private Floor createNewFloor(String buildingIndex, String floorIndex) {
        Integer tenantId = TenantContextHolder.DEFAULT_TENANT_ID;
        Building building = createNewBuilding(buildingIndex);
        Floor floor = floorService.lambdaQuery()
                .eq(Floor::getBuildingId, building.getId())
                .eq(Floor::getName, floorIndex).one();
        if (ObjectUtil.isNotEmpty(floor)) {
            return floor;
        }
        floor = new Floor();
        floor.setTenantId(tenantId);
        floor.setName(floorIndex);
        floor.setBuildingId(building.getId());
        //离床时间阈值
        floor.setOutBedTimeout(building.getOutBedTimeout());
        floor.setOutBedTimeoutUnified(building.getOutBedTimeoutUnified());
        //监测时间
        floor.setMonitorTimeUnified(building.getMonitorTimeUnified());
        int count = floorService.getBaseMapper().insert(floor);
        List<TimePeriodParam> monitorTimeByObjIdandtype = monitorTimeService.getMonitorTimeByObjIdAndType(building.getId(), SystemConfigService.TYPE_TAKE_EVENT_TIMEOUT);
        if (CollUtil.isNotEmpty(monitorTimeByObjIdandtype)) {
            for (TimePeriodParam mtq : monitorTimeByObjIdandtype) {
                MonitorTime monitorTime = new MonitorTime();
                BeanUtils.copyProperties(mtq, monitorTime);
                monitorTime.setObjId(floor.getId());
                monitorTime.setType(SystemConfigService.TYPE_OUT_BED_TIMEOUT);
                monitorTimeService.getBaseMapper().insert(monitorTime);
            }
        } else {
            List<TimePeriodParam> monitorTimeList = systemConfigService.getDefaultMonitorTime();
            for (TimePeriodParam sc : monitorTimeList) {
                MonitorTime monitorTime = new MonitorTime();
                monitorTime.setStartTime(sc.getStartTime());
                monitorTime.setEndTime(sc.getEndTime());
                monitorTime.setObjId(floor.getId());
                monitorTime.setType(SystemConfigService.TYPE_OUT_BED_TIMEOUT);
                monitorTimeService.getBaseMapper().insert(monitorTime);
            }
        }
        if (count > 0) {
            return floor;
        }
        throw new RuntimeException("新增层失败");
    }

    /**
     * 创建新楼
     *
     * @param buildingIndex 楼唯一标识
     * @return
     */
    private Building createNewBuilding(String buildingIndex) {
        Integer tenantId = TenantContextHolder.DEFAULT_TENANT_ID;
        Building building = buildingService.lambdaQuery().eq(Building::getName, buildingIndex).one();
        if (ObjectUtil.isNotEmpty(building)) {
            return building;
        }
        building = new Building();
        building.setTenantId(tenantId);
        building.setName(buildingIndex);
        building.setOutBedTimeoutUnified(1);
        building.setMonitorTimeUnified(1);
        //默认离床时间阀值
        String outBedTimeout = systemConfigService.getDefaultOutBedTimeout();
        building.setOutBedTimeout(outBedTimeout);
        int count = buildingService.getBaseMapper().insert(building);
        //默认监控时间
        List<TimePeriodParam> monitorTimeList = systemConfigService.getDefaultMonitorTime();
        for (TimePeriodParam sc : monitorTimeList) {
            MonitorTime monitorTime = new MonitorTime();
            monitorTime.setStartTime(sc.getStartTime());
            monitorTime.setEndTime(sc.getEndTime());
            monitorTime.setObjId(building.getId());
            monitorTime.setType(SystemConfigService.TYPE_TAKE_EVENT_TIMEOUT);
            monitorTimeService.getBaseMapper().insert(monitorTime);
        }
        if (count > 0) {
            return building;
        }
        throw new RuntimeException("新增楼失败");
    }

    /**
     * 转换床  监控时间
     *
     * @param monitorTimes
     * @return
     */
    private List<MonitorTimeVO> getMonitorTime(List<MonitorTime> monitorTimes) {
        List<MonitorTimeVO> monitorTimeVOS = new ArrayList<>();
        for (MonitorTime mt : monitorTimes) {
            MonitorTimeVO monitorTimeVO = new MonitorTimeVO();
            monitorTimeVO.setId(mt.getId());
            monitorTimeVO.setStartTime(mt.getStartTime());
            monitorTimeVO.setEndTime(mt.getEndTime());
            monitorTimeVOS.add(monitorTimeVO);
        }
        return monitorTimeVOS;
    }

    /**
     * 查询层
     *
     * @return
     */
    private List<MonitorInfoTreeVO> getFloor(Integer floorId, Integer roomId, Integer bedId) {
        List<MonitorInfoTreeVO> floorList = new ArrayList<>();
        Floor floor = floorService.lambdaQuery().eq(Floor::getId, floorId).one();
        MonitorInfoTreeVO monitorInfoTreeVO = new MonitorInfoTreeVO();
        monitorInfoTreeVO.setId(BedService.TREE_FLOOR_PREFIX + floor.getId());
        monitorInfoTreeVO.setKey(monitorInfoTreeVO.getId());
        monitorInfoTreeVO.setName(floor.getName());
        monitorInfoTreeVO.setType(BedService.TYPE_FLOOR);
        monitorInfoTreeVO.setMonitorTimeUnified(floor.getMonitorTimeUnified());
        monitorInfoTreeVO.setOutBedTimeoutUnified(floor.getOutBedTimeoutUnified());
        monitorInfoTreeVO.setOutBedTime(floor.getOutBedTimeout());
        List<MonitorTime> monitorTimes = monitorTimeService.lambdaQuery().eq(MonitorTime::getType, BedService.TYPE_FLOOR).eq(MonitorTime::getObjId, floor.getId()).list();
        List<MonitorTimeVO> monitorTime = getMonitorTime(monitorTimes);
        monitorInfoTreeVO.setMonitorTimes(monitorTime);
        monitorInfoTreeVO.setChildren(getRoom(roomId, bedId));
        floorList.add(monitorInfoTreeVO);
        return floorList;
    }

    /**
     * 查询房间
     *
     * @return
     */
    private List<MonitorInfoTreeVO> getRoom(Integer roomId, Integer bedId) {
        List<MonitorInfoTreeVO> roomList = new ArrayList<>();
        Room room = roomService.lambdaQuery().eq(Room::getId, roomId).one();
        MonitorInfoTreeVO monitorInfoTreeVO = new MonitorInfoTreeVO();
        monitorInfoTreeVO.setId(BedService.TREE_ROOM_PREFIX + room.getId());
        monitorInfoTreeVO.setKey(monitorInfoTreeVO.getId());
        monitorInfoTreeVO.setName(room.getName());
        monitorInfoTreeVO.setType(BedService.TYPE_ROOM);
        monitorInfoTreeVO.setMonitorTimeUnified(room.getMonitorTimeUnified());
        monitorInfoTreeVO.setOutBedTimeoutUnified(room.getOutBedTimeoutUnified());
        monitorInfoTreeVO.setOutBedTime(room.getOutBedTimeout());
        List<MonitorTime> monitorTimes = monitorTimeService.lambdaQuery().eq(MonitorTime::getType, BedService.TYPE_ROOM).eq(MonitorTime::getObjId, room.getId()).list();
        List<MonitorTimeVO> monitorTime = getMonitorTime(monitorTimes);
        monitorInfoTreeVO.setMonitorTimes(monitorTime);
        monitorInfoTreeVO.setChildren(getBed(bedId));
        roomList.add(monitorInfoTreeVO);
        return roomList;
    }

    /**
     * 查询床
     *
     * @param id
     * @return
     */
    private List<MonitorInfoTreeVO> getBed(Integer id) {
        List<MonitorInfoTreeVO> bedList = new ArrayList<>();
        Bed bed = bedService.lambdaQuery().eq(Bed::getId, id).one();
        MonitorInfoTreeVO monitorInfoTreeVO = new MonitorInfoTreeVO();
        monitorInfoTreeVO.setId(String.valueOf(bed.getId()));
        monitorInfoTreeVO.setKey(monitorInfoTreeVO.getId());
        monitorInfoTreeVO.setName(bed.getName());
        monitorInfoTreeVO.setType(BedService.TYPE_BED);
        monitorInfoTreeVO.setOutBedTime(bed.getOutBedTimeout());
        List<BedMonitorTime> monitorTimes = bedMonitorTimeService.lambdaQuery().eq(BedMonitorTime::getBedId, bed.getId()).list();
        List<MonitorTimeVO> monitorTime = getBedMonitorTime(monitorTimes);
        monitorInfoTreeVO.setMonitorTimes(monitorTime);
        monitorInfoTreeVO.setMonitorTimeUnified(1);
        monitorInfoTreeVO.setOutBedTimeoutUnified(1);
        bedList.add(monitorInfoTreeVO);
        return bedList;
    }

    /**
     * 转换楼层房间  监控时间
     *
     * @param monitorTimes
     * @return
     */
    private List<MonitorTimeVO> getBedMonitorTime(List<BedMonitorTime> monitorTimes) {
        List<MonitorTimeVO> monitorTimeVOS = new ArrayList<>();
        for (BedMonitorTime mt : monitorTimes) {
            MonitorTimeVO monitorTimeVO = new MonitorTimeVO();
            monitorTimeVO.setId(mt.getId());
            monitorTimeVO.setStartTime(mt.getStartTime());
            monitorTimeVO.setEndTime(mt.getEndTime());
            monitorTimeVOS.add(monitorTimeVO);
        }
        return monitorTimeVOS;
    }
}
